#ifndef _STORAGE_PROTOCOL_H
#define _STORAGE_PROTOCOL_H

#include "NetworkProtocol.h"
#include <cstdio>
#include <map>
#include <boost/filesystem/path.hpp>

/**
 * Klasa obsługująca protokół storage. Tworzona przez Client jako singleton.
 */
class StorageProtocol : public CSNetworkLib::NetworkProtocol
{
	public:
		/**
		 * Konstruktor podstawowy
		 * @param s socket używane do połączenia.
		 */
		StorageProtocol(socket_ptr s);
		/**
		 * Destruktor domyślny, wirtualny.
		 */
		~StorageProtocol();

		/**
		 * Metoda przeprowadza autoryzację storage.
		 * @param name nazwa storage
		 * @param key klucz (hasło)
		 * @return true jeśli autoryzacja się powiodła, false jeśli nie.
		 */
		bool Auth(const std::string &name, const std::string &key);

		/**
		 * Metoda pobiera informacje o pliku i wysyła rządanie aktualizacji do serwera centralnego.
		 * @param link ścieżka do pliku
		 * @param force parametr nie używany, powiązany z SendUnique
		 * @return true jeśli update został wysłany.
		 */
		bool SendFileInfo(	const boost::filesystem::path &link, bool force = false);

		/**
		 * Metoda pobiera informacje o folderze i wysyła rządanie aktualizacji do serwera centralnego.
		 * @param link ścieżka do folderu
		 * @param sync flaga informująca że aktualizacja została wysłana w wyniku synchronizacji folderu.
		 * @param force parametr nie używany, powiązany z SendUnique
		 * @return true jeśli update został wysłany.
		 */
		bool SendFolderInfo( const boost::filesystem::path &link, bool sync, bool force = false);
	protected:
	    /**
		 * Mapa otwartych plików, pliki zostaną automatycznie zamknięte podczas rozłączania storage jeśli nie zrobi tego wcześniej użytkownik.
		 */
		std::map<FILE*, std::string> m_openFiles;
		/**
		 * Metoda sprawdza czy plik jest otwarty
		 * @param handle uchwyt do pliku
		 * @return true jeśli plik jest otwarty i uchwyt jest poprawny
		 */
		bool IsOpenFile(FILE* handle);
	private:

		/**
		 * Metoda obsługuje żądanie sprawdzenie typu zasobu.
		 *
		 * Format pakietu wejściowego:
		 * 	    bool - extended, 
		 * 	    string - link/parent link, 
		 * 		string - name (optional);
		 * Format pakietu wyjściowego:
		 *   	uint8 - type (0 - none, 1 - file, 2 - folder), 
		 *		string - link, 
		 *		string - name
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnGetType(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie otwarcia pliku
		 *
		 * Format pakietu wejściowego:
		 *		string - link/parent link, 
		 *	    string - type ("r", "a+", "w", ...), 
		 * 		string - name (optional);
		 * Format pakietu wyjściowego:
		 *		uint32_t - handle (0 - on error)
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnFileOpen(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żadanie zamknięcia pliku
		 *
		 * Format pakietu wejściowego:
		 *		uint32_t - handle
		 * Format pakietu wyjściowego:
		 *		uint32_t - code (0 - success, 1 - file was closed, 2 - failed to close)
		 * @param request pakiet żądania
		 */
		void OnFileClose(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żadania informacji o pliku
		 *
		 * Format pakietu wejściowego:
		 *		uint32_t - handle
         *      uint8_t dataType (0 - size, 1 - timestamp, 2 - position)
		 * Format pakietu wyjściowego:
		 *		uint64 - żądane dane
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnFileInfo(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje ustawienie kursora pliku
		 *
		 * Format pakietu wejściowego:
		 *		uint32_t - handle;
		 *		int64 - newPosition (w przypadku liczby ujemnej pozycja ustawiana jest od końca)
		 * Format pakietu wyjściowego:
		 *		bool - status - true/false
		 * @param request pakiet żądania
		 */
		void OnFileSeek(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje sprawdzenie pliku pod względem feof.
		 *
		 * Format pakietu wejściowego:
		 *		uint32_t - handle;
		 * Format pakietu wyjściowego:
		 *		bool - status - true/false
		 * @param request pakiet żądania
		 */
		void OnFileEof(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie wpisania danych do pliku
		 *
		 * Format pakietu wejściowego:
		 *		uint32_t - handle;
		 *		char* - buffor
		 * Format pakietu wyjściowego:
		 *		int32_t - ilość bajtów wpisanych (-1 on error)
		 * @param request pakiet żądania
		 */
		void OnFileWrite(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie odczytania danych z pliku
		 *
		 * Format pakietu wejściowego:
		 *		uint32_t - handle;
		 *		uint32_t - size
		 * Format pakietu wyjściowego:
		 *		int32_t - ilośc bajtów odczytanych (-1 on error)
		 *		char* - buffor (jeśli count>0)
		 * @param request pakiet żądania
		 */
		void OnFileRead(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie usunięcia pliku
		 *
		 * Format pakietu wejściowego:
		 *		string  - link
		 * Format pakietu wyjściowego:
		 *		int16_t - code (0 - on success, -1 - system fail
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnFileDelete(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie przeniesienia pliku.
		 *
		 * Format pakietu wejściowego:
		 *		string  - link
		 *		string  - new link (folder)
		 *		string -  new name
		 *		bool - force operation
		 * Format pakietu wyjściowego:
		 *		int16_t - code (0 - on success, -1 - system fail, -2 - file under link exists
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnFileMove(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie skopiowania pliku.
		 * 
		 * Format pakietu wejściowego:
		 *		string  - link
		 *		string  - new link (folder)
		 *		string -  new name
		 *		bool - force operation
		 * Format pakietu wyjściowego:
		 *		int16_t - code (0 - on success, -1 - system fail, -2 - file under link exists, -3 - target file in use)
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnFileCopy(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie synchronizacji zawartości folderu (dir, ls).
		 *
		 * Format pakietu wejściowego:
		 *		string - link
		 *		bool - recursive (default, false);
		 * Format pakietu wyjściowego:
		 *		int16_t - code(-1 if folder dont exists)
		 * Metoda wysyła pakiety synchronizacyjne.
		 * @param request pakiet żądania
		 */
		void OnFolderSync(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żadanie utworzenia folderu.
		 *
		 * Format pakietu wejściowego:
		 *		string - link - parent folder
		 *	 	string - subfolder path/name
		 * Format pakietu wyjściowego:
         *      bool - status - true/false
		 * Metoda wysyła pakiet synchronizacyjny.
		 * @param request pakiet żądania
		 */
		void OnFolderCreate(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie przeniesienia folderu.
		 * METODA NIE ZAIMPLEMENTOWANA
		 *
		 * Format pakietu wejściowego:
		 *		string - link
		 *		string  - new link (folder)
		 *		string -  new name
		 *		bool - force
		 * Format pakietu wyjściowego:
		 *		int32_t - code (0 - on success, -1 - system fail)
		 *		string - link
		 * @param request pakiet żądania
		 */
		void OnFolderMove(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie skopiowania folderu.
		 * METODA NIE ZAIMPLEMENTOWANA
		 *
		 * Format pakietu wejściowego:
		 *		string - link
		 *		string  - new link (folder)
		 *		string -  new name
		 *		bool - force
		 * Format pakietu wyjściowego:
		 *		int32_t - code (0 - on success, -1 - system fail)
		 *		string - link
		 * @param request pakiet żądania
		 */
		void OnFolderCopy(const CSNetworkLib::NetworkPacket &request);

		/**
		 * Metoda obsługuje żądanie usunięcia folderu.
		 * METODA NIE ZAIMPLEMENTOWANA
		 *
		 * Format pakietu wejściowego:
		 *		string - link
		 *		bool - force
		 * Format pakietu wyjściowego:
		 *		int32_t - code (0 - on success, -1 - system fail)
		 * @param request pakiet żądania
		 */
		void OnFolderDelete(const CSNetworkLib::NetworkPacket &request);
};

#endif
